﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace SRCBQuestionnaireStatistic
{
    public static class Utility
    {
        public static string GetAttributeValue(XmlNode node, string key, string defaultValue)
        {
            XmlAttribute attribute = null;
            foreach (XmlAttribute attr in node.Attributes)
            {
                if (attr.Name.Equals(key, StringComparison.OrdinalIgnoreCase))
                {
                    attribute = attr;
                    break;
                }
            }

            string result = defaultValue;

            if (attribute != null)
                result = attribute.Value.Trim();

            return result;
        }

        public static Model.Answer.Symbol ConvertToSymbol(string sym)
        {
            switch (sym)
            {
                case "A":
                    return Model.Answer.Symbol.A;
                case "B":
                    return Model.Answer.Symbol.B;
                case "C":
                    return Model.Answer.Symbol.C;
                case "D":
                    return Model.Answer.Symbol.D;
                case "E":
                    return Model.Answer.Symbol.E;
                case "F":
                    return Model.Answer.Symbol.F;
                case "G":
                    return Model.Answer.Symbol.G;
                case "H":
                    return Model.Answer.Symbol.H;
                case "I":
                    return Model.Answer.Symbol.I;
                case "J":
                    return Model.Answer.Symbol.J;
                case "K":
                    return Model.Answer.Symbol.K;
                default:
                    throw new NotSupportedException(string.Format("{0} is not supported", sym));
            }
        }

        public static Model.Question.Typee ConvertToTypee(string type)
        {
            switch (type)
            {
                case "SingleChoice":
                    return Model.Question.Typee.SingleChoice;
                case "MultipleChoices":
                    return Model.Question.Typee.MultipleChoices;
                default:
                    throw new NotSupportedException(string.Format("{0} is not supported", type));
            }
        }
        public static int ConvertToIndex(string sym)
        {
            switch (sym)
            {
                case "A":
                case "a":
                    return 0;
                case "B":
                case "b":
                    return 1;
                case "C":
                case "c":
                    return 2;
                case "D":
                case "d":
                    return 3;
                case "E":
                case "e":
                    return 4;
                case "F":
                case "f":
                    return 5;
                case "G":
                case "g":
                    return 6;
                case "H":
                case "h":
                    return 7;
                case "I":
                case "i":
                    return 8;
                case "J":
                case "j":
                    return 9;
                default:
                    return -1;
            }
        }
        public static Model.Answer.Symbol ConvertToSymbol(int index)
        {
            switch (index)
            {
                case 0:
                    return Model.Answer.Symbol.A;
                case 1:
                    return Model.Answer.Symbol.B;
                case 2:
                    return Model.Answer.Symbol.C;
                case 3:
                    return Model.Answer.Symbol.D;
                case 4:
                    return Model.Answer.Symbol.E;
                case 5:
                    return Model.Answer.Symbol.F;
                case 6:
                    return Model.Answer.Symbol.G;
                case 7:
                    return Model.Answer.Symbol.H;
                case 8:
                    return Model.Answer.Symbol.I;
                case 9:
                    return Model.Answer.Symbol.J;
                case 10:
                    return Model.Answer.Symbol.K;
                default:
                    throw new NotSupportedException(string.Format("{0} is not supported", index));
            }
        }

        public static int MoreCharToInt(string value)
        {
            int rtn = 0;
            int powIndex = 0;

            for (int i = value.Length - 1; i >= 0; i--)
            {
                int tmpInt = value[i];
                tmpInt -= 64;

                rtn += (int)Math.Pow(26, powIndex) * tmpInt;
                powIndex++;
            }

            return rtn;
        }

        public static string IntToMoreChar(int value)
        {
            string rtn = string.Empty;
            List<int> iList = new List<int>();

            //To single Int
            while (value / 26 != 0 || value % 26 != 0)
            {
                iList.Add(value % 26);
                value /= 26;
            }

            //Change 0 To 26
            for (int j = 0; j < iList.Count - 1; j++)
            {
                if (iList[j] == 0)
                {
                    iList[j + 1] -= 1;
                    iList[j] = 26;
                }
            }

            //Remove 0 at last
            if (iList[iList.Count - 1] == 0)
            {
                iList.Remove(iList[iList.Count - 1]);
            }

            //To String
            for (int j = iList.Count - 1; j >= 0; j--)
            {
                char c = (char)(iList[j] + 64);
                rtn += c.ToString();
            }

            return rtn;
        }

        #region XML Utilities
        public static void GenerateAnswers(string xmlPath)
        {
            XmlTextWriter answersWriter = new XmlTextWriter(xmlPath, Encoding.UTF8);
            answersWriter.Formatting = Formatting.Indented;

            answersWriter.WriteStartDocument();
            answersWriter.WriteStartElement("survey");
            answersWriter.WriteStartElement("index");
            answersWriter.WriteEndElement();
            answersWriter.WriteStartElement("owner");
            answersWriter.WriteEndElement();
            answersWriter.WriteStartElement("title");
            answersWriter.WriteEndElement();
            answersWriter.WriteEndElement();
            answersWriter.WriteEndDocument();
            answersWriter.Close();
        }

        public static void AddStatisticsColumns(XmlDocument statisticsDocument, string[] syms, string[] texts)
        {
            XmlElement columns = (XmlElement)statisticsDocument.GetElementsByTagName("columns")[0];

            if (syms.Length > columns.ChildNodes.Count)
            {
                columns.RemoveAll();
                for (int index = 0; index < syms.Length; index++)
                {
                    XmlNode node = statisticsDocument.CreateElement(syms[index]);
                    node.InnerText = texts[index];
                    columns.AppendChild(node);
                }
            }
            else
            {
                // nothing to do...
            }
        }

        public static void GenerateStatistics(string xmlPath)
        {
            XmlTextWriter statisticsWriter = new XmlTextWriter(xmlPath, Encoding.UTF8);
            statisticsWriter.Formatting = Formatting.Indented;

            statisticsWriter.WriteStartDocument();

            statisticsWriter.WriteProcessingInstruction("xml-stylesheet", "type='text/xsl' href='..\\..\\..\\..\\statistic.xsl'");
            statisticsWriter.WriteStartElement("statistics");
            statisticsWriter.WriteStartElement("index");
            statisticsWriter.WriteEndElement();
            statisticsWriter.WriteStartElement("owner");
            statisticsWriter.WriteEndElement();
            statisticsWriter.WriteStartElement("role");
            statisticsWriter.WriteEndElement();
            statisticsWriter.WriteStartElement("year");
            statisticsWriter.WriteEndElement();
            statisticsWriter.WriteStartElement("title");
            statisticsWriter.WriteEndElement();
            statisticsWriter.WriteStartElement("columns");
            statisticsWriter.WriteEndElement();
            statisticsWriter.WriteStartElement("total");
            statisticsWriter.WriteEndElement();
            statisticsWriter.WriteEndDocument();
            statisticsWriter.Close();
        }

        public static void FillAnswersUp(XmlDocument statisticsDocument, string defaultValue)
        {
            XmlNodeList sQuestions = statisticsDocument.GetElementsByTagName("sQuestion");

            XmlNodeList columns = statisticsDocument.GetElementsByTagName("columns")[0].ChildNodes;

            foreach (XmlNode question in sQuestions)
            {
                XmlNodeList answers = question["answer"].ChildNodes;
                if (answers.Count < columns.Count)
                {
                    for (int index = answers.Count; index < columns.Count; index++)
                    {
                        XmlNode newNode = columns[index].Clone();
                        newNode.InnerText = defaultValue;
                        question["answer"].AppendChild(newNode);
                    }
                }

            }
        }

        public static XmlElement AppendStatisticsQuestion(XmlDocument statisticsDocument, string[] answers)
        {
            XmlElement sQuestion = statisticsDocument.CreateElement("sQuestion");

            try
            {
                XmlElement statistics = statisticsDocument.DocumentElement;

                XmlElement qIndex = statisticsDocument.CreateElement("qIndex");
                XmlElement answer = statisticsDocument.CreateElement("answer");
                XmlElement type = statisticsDocument.CreateElement("type");
                XmlElement answerElement = null;

                foreach (string singleAnswer in answers)
                {
                    if (!string.IsNullOrEmpty(singleAnswer))
                    {
                        answerElement = statisticsDocument.CreateElement(singleAnswer);
                        answerElement.InnerText = "0";
                        answer.AppendChild(answerElement);
                    }
                }

                sQuestion.AppendChild(qIndex);
                sQuestion.AppendChild(type);
                sQuestion.AppendChild(answer);

                XmlNodeList sQuestions = statisticsDocument.GetElementsByTagName("sQuestion");

                if (sQuestions.Count >= 0)
                {
                    statisticsDocument.LastChild.AppendChild(sQuestion);
                }                
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            { }

            return sQuestion;
        }

        public static XmlElement AppendAnswer(XmlDocument statisticsDocument, XmlElement statisticQuestion, string[] answers)
        {
            XmlNodeList answerList = statisticQuestion["answer"].ChildNodes;
            XmlElement answerElement = null;

            foreach (string answer in answers)
            {
                bool doesAnswerExist = false;
                foreach (XmlNode answerNode in answerList)
                {
                    if (string.Equals(answerNode.Name, answer))
                    {
                        doesAnswerExist = true;
                        break; // The answer exists, nothing to do.
                    }
                }

                if (!doesAnswerExist)
                {
                    answerElement = statisticsDocument.CreateElement(answer);
                    statisticQuestion["answer"].AppendChild(answerElement);
                    answerList = statisticQuestion["answer"].ChildNodes;
                }
            }

            return statisticQuestion;
        }

        public static XmlElement AppendSurvey(XmlDocument answersDocument)
        {
            XmlElement survey = answersDocument.CreateElement("survey");
            try
            {
                XmlElement answers = answersDocument.DocumentElement;
                
                XmlElement index = answersDocument.CreateElement("index");
                XmlElement owner = answersDocument.CreateElement("owner");

                survey.AppendChild(index);
                survey.AppendChild(owner);
                answers.AppendChild(survey);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            { }

            return survey;
        }

        public static XmlElement AppendQuestionnarie(XmlDocument answersDocument)
        {
            XmlElement questionnaire = answersDocument.CreateElement("questionnaire");
            
            try
            {
                XmlElement answers = answersDocument.DocumentElement;
                XmlNodeList surveys = answersDocument.GetElementsByTagName("survey");

                if (surveys.Count >= 0)
                {

                    XmlElement qnIndex = answersDocument.CreateElement("qnIndex");
                    questionnaire.AppendChild(qnIndex);
                    //XmlElement qnTitle = answersDocument.CreateElement("qnTitle");
                    //questionnaire.AppendChild(qnTitle);

                    surveys[surveys.Count - 1].AppendChild(questionnaire);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                
            }

            return questionnaire;
        }

        public static XmlElement AppendQuestion(XmlDocument answersDocument)
        {
            XmlElement question = answersDocument.CreateElement("question");

            try
            {
                XmlElement answers = answersDocument.DocumentElement;
                XmlNodeList questionnaires = answersDocument.GetElementsByTagName("questionnaire");

                if (questionnaires.Count >= 0)
                {
                    XmlElement index = answersDocument.CreateElement("qIndex");
                    //XmlElement boss = answersDocument.CreateElement("boss");
                    //XmlElement branch = answersDocument.CreateElement("branch");
                    XmlElement content = answersDocument.CreateElement("content");
                    XmlElement answer = answersDocument.CreateElement("answer");

                    question.AppendChild(index);
                    //question.AppendChild(boss);
                    //question.AppendChild(branch);
                    question.AppendChild(content);
                    question.AppendChild(answer);

                    questionnaires[questionnaires.Count - 1].AppendChild(question);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            { }

            return question;
        }

        public static void UpdateStatistic(XmlDocument statisticDocument, string statisticIndex, string ownerName, string year, string title)
        {
            statisticDocument.GetElementsByTagName("index")[0].InnerText = statisticIndex;
            statisticDocument.GetElementsByTagName("owner")[0].InnerText = ownerName;
            statisticDocument.GetElementsByTagName("year")[0].InnerText = year;
            statisticDocument.GetElementsByTagName("title")[0].InnerText = title;
        }

        public static void UpdateSurvey(XmlDocument answersDocument, string surveyIndex, string ownerName, string title)
        {
            answersDocument.GetElementsByTagName("index")[0].InnerText = surveyIndex;
            answersDocument.GetElementsByTagName("owner")[0].InnerText = ownerName;
            answersDocument.GetElementsByTagName("title")[0].InnerText = title;
        }

        public static void UpdateStatisticQuestion(XmlElement statisticQuestion, string qIndex, string[] answers)
        {
            if (string.IsNullOrEmpty(statisticQuestion["qIndex"].InnerText))
            {
                statisticQuestion["qIndex"].InnerText = qIndex;
            }

            XmlNodeList answerList = statisticQuestion["answer"].ChildNodes;

            foreach (XmlNode answerNode in answerList)
            {
                foreach (string answer in answers)
                {
                    if (string.Equals(answer, answerNode.Name))
                    {
                        int count = 1;
                        string currentCount = answerNode.InnerText;
                        if (!string.IsNullOrEmpty(currentCount))
                        {
                            count = int.Parse(currentCount);
                            count++;
                        }

                        answerNode.InnerText = count.ToString();
                    }
                }
            }
        }

        public static void UpdateQuestionnaire(XmlElement currentQuestionnaire, string subject)
        {
            //XmlNodeList questionnaires = currentSurvey.GetElementsByTagName("questionnaire");
            //XmlElement questionnaire = null;

            //if (questionnaires.Count > 0)
            //{
            //    questionnaire = (XmlElement)questionnaires[questionnaires.Count - 1];
                int questionnaireIndex = 1;

                if (string.Compare(currentQuestionnaire.PreviousSibling.Name, "title") != 0)
                {
                    string previousSiblingIndex = currentQuestionnaire.PreviousSibling.FirstChild.InnerText;
                    questionnaireIndex = int.Parse(previousSiblingIndex);
                    questionnaireIndex++; 
                }

                currentQuestionnaire["qnIndex"].InnerText = questionnaireIndex.ToString();
                //currentQuestionnaire["qnTitle"].InnerText = subject;
            //}

            //return questionnaire;
        }

        public static void UpdateQuestion(XmlElement currentQuestion, string content, string answer)
        {
            int questionIndex = 1;

            if (string.Compare(currentQuestion.PreviousSibling.Name, "qnIndex") != 0)
            {
                string previousSiblingIndex = currentQuestion.PreviousSibling["qIndex"].InnerText;
                questionIndex = int.Parse(previousSiblingIndex);
                questionIndex++;
            }

            currentQuestion["qIndex"].InnerText = questionIndex.ToString();
            if (!string.IsNullOrEmpty(content))
            {
                currentQuestion["content"].InnerText = content;
            }
            currentQuestion["answer"].InnerText = answer;
 
        }

        public static XmlNode RetrieveNodeByTagNameAndIndex(XmlDocument answersDocumet, string elementTagName, int index)
        {
            XmlNodeList nodes = answersDocumet.GetElementsByTagName(elementTagName);

            XmlNode returnValue = null;

            if (nodes.Count > 0)
            {
                if (index != -1)
                {
                    returnValue = nodes[index];
                }
                else
                {
                    returnValue = nodes[nodes.Count - 1]; // Returns the last node if [index] equals -1.
                }
            }

            return returnValue;
        }

        public static XmlNode RetrieveNodeByTagNameAndIndex2(XmlElement element, string elementTagName, int index)
        {
            XmlNodeList nodes = element.GetElementsByTagName(elementTagName);

            XmlNode returnValue = null;

            if (nodes.Count > 0)
            {
                if (index != -1)
                {
                    returnValue = nodes[index];
                }
                else
                {
                    returnValue = nodes[nodes.Count - 1]; // Returns the last node if [index] equals -1.
                }
            }

            return returnValue;
        }

        public static int RetrieveCountOfChildrenByName(XmlElement element, string elementTagName)
        {
            XmlNodeList nodes = element.GetElementsByTagName(elementTagName);

            return nodes.Count;
        }

        #endregion XML Utilities
    }
}
